package com.meng.mini.spring.context;

import com.meng.mini.spring.beans.XmlBeanDefinitionReader;
import com.meng.mini.spring.beans.BeanDefinition;
import com.meng.mini.spring.beans.BeansException;
import com.meng.mini.spring.beans.BeanFactory;
import com.meng.mini.spring.beans.SimpleBeanFactory;
import com.meng.mini.spring.core.ClassPathXmlResource;
import com.meng.mini.spring.core.Resource;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Meng Xu
 * @version 1.0.0 解析在xml中记录的 bean
 * @date 2024-01-15 16:59
 **/
public class ClassPathXmlApplicationContext implements BeanFactory, ApplicationEventPublisher {

    private SimpleBeanFactory  beanFactory;


    /**
     * bean 信息 容器
     * OS: BeanDefinition 中存储 bean信息 id classpath 信息等
     */
    private List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();

    /**
     * 实例容器
     */
    private Map<String, Object> singletons = new HashMap<String, Object>();


    /**
     * 构造器获取外部配置，解析出Bean的定义，形成内存映射
     * @param fileName xml 文件路劲
     */
    public ClassPathXmlApplicationContext(String fileName){
        Resource resource = new ClassPathXmlResource(fileName);
        SimpleBeanFactory beanFactory = new SimpleBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        reader.loadBeanDefinitions(resource);
        this.beanFactory = beanFactory;
    }

    /**
     * 外部获取 bean实例方法
     * @param beanName mini spring bean id
     * @return 对应实例
     */
    public Object getBean(String beanName) throws BeansException {
//        return singletons.get(beanName);
        return this.beanFactory.getBean(beanName);
    }

    @Override
    public boolean containsBean(String name) {
        return this.beanFactory.containsBean(name);
    }

    @Override
    public boolean isPrototype(String name) {
        return false;
    }

    @Override
    public Class<?> getType(String name) {
        return null;
    }
    /**
     * 注册 一个definition
     */
    public void registerBean(String beanName, Object obj) {
        this.beanFactory.registerBean(beanName, obj);
    }

    @Override
    public void publishEvent(ApplicationEvent event) {
    }


    /**
     * 读取 xml bean信息配置
     * @param fileName 文件名称路径
     */
    public void readXml(String fileName){
        SAXReader saxReader = new SAXReader();
        try {
            URL xmlPath = this.getClass().getClassLoader().getResource(fileName);
            Document document = saxReader.read(xmlPath);
            Element rootElement = document.getRootElement();
            //获取配置文件xml 中每一个bean，进行处理
            for (Element element : rootElement.elements()) {
                //获取bean的基本信息
                String  beanId = element.attributeValue("id");
                String beanClassName = element.attributeValue("class");
                BeanDefinition beanDefinition = new BeanDefinition(beanId, beanClassName);

                //将beanDefinition 放入内存容器 beanDefinitions 中

                beanDefinitions.add(beanDefinition);
            }
        } catch(Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 利用反射创建bean实例， 并存储在 singletons 中
     */
    private void instanceBeans(){
        for (BeanDefinition beanDefinition : beanDefinitions) {
            try {
                singletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());
            } catch (Exception e){
                e.printStackTrace();
            }

        }
    }

    /*
    1-1-2
    one:
        Burpee
        Long Jump Reset
        Combo: Burpee Long Jump Reset

    two:
        Mountain Climber
        Lateral Plank
        Combo: Mountain Climber x 4 + Lateral Plank X 2

    three:
        虫爬向前 向后 + Squat Jump
        Lateral Squat Jump
        Combo: 虫爬向前 向后 + Lateral Squat Jump

    Tri Set
    one
        Skater(L)x1 + Sprint Run x 4(R)
        平板支撑脚开合提手肘
        Skater(R)x1 + Sprint Run x 4(L)
    two
        power lunge
        平板支撑脚开合提手肘
        power lunge
    three
        三步侧移+下肢转体90°
        平板支撑脚开合提手肘
        三步侧移+下肢转体90°

    four
        Skater(L)x1 + Sprint Run x 4(R)
        交替登山跑(L+R) x1 + Pushup x1
        Skater(L)x1 + Sprint Run x 4(R)
    five
        power lunge
        交替登山跑(L+R) x1 + Pushup x1
        power lunge
    six
        三步侧移+下肢转体90°
        交替登山跑(L+R) x1 + Pushup x1
        三步侧移+下肢转体90°



     */

}
